package com.lyf.boot.handler;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.lyf.boot.constant.TioConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.tio.core.ChannelContext;
import org.tio.core.Tio;
import org.tio.http.common.HttpRequest;
import org.tio.http.common.HttpResponse;
import org.tio.utils.lock.SetWithLock;
import org.tio.websocket.common.WsRequest;
import org.tio.websocket.common.WsResponse;
import org.tio.websocket.common.WsSessionContext;
import org.tio.websocket.server.handler.IWsMsgHandler;

import java.nio.ByteBuffer;

/**
 * @author Luyufan
 * @date 2023/7/5 15:58
 */
@Slf4j
@Component
public class TioServerHandler implements IWsMsgHandler {

    /**
     * 握手
     *
     * @param httpRequest    请求
     * @param httpResponse   响应
     * @param channelContext 通道
     * @return 响应
     * @throws Exception 异常
     */
    @Override
    public HttpResponse handshake(HttpRequest httpRequest, HttpResponse httpResponse, ChannelContext channelContext) throws Exception {
        // userId
        String userId = httpRequest.getParam(TioConstant.USER_ID);
        Tio.bindUser(channelContext, userId);
        // 绑定群组
        return httpResponse;
    }

    /**
     * 完成握手后
     *
     * @param httpRequest    请求
     * @param httpResponse   响应
     * @param channelContext 通道
     * @throws Exception 异常
     */
    @Override
    public void onAfterHandshaked(HttpRequest httpRequest, HttpResponse httpResponse, ChannelContext channelContext) throws Exception {
        // ws://127.0.0.1:8888?userId=1
        log.info("已连接成功");
        //绑定到群组，后面会有群发
        Tio.bindGroup(channelContext.tioConfig, "1", "1");
        int count = Tio.getAll(channelContext.tioConfig).getObj().size();

        String msg = "{name:'admin',message:'" + channelContext.userid + " 进来了，共【" + count + "】人在线" + "'}";
        //用tio-websocket，服务器发送到客户端的Packet都是WsResponse
        WsResponse wsResponse = WsResponse.fromText(msg, TioConstant.CHARSET);
        //群发
        Tio.sendToGroup(channelContext.tioConfig, "1", wsResponse);
    }

    /**
     * 收到字节信息
     *
     * @param wsRequest      请求
     * @param bytes          字节数组
     * @param channelContext 通道
     * @return ByteBuffer
     * @throws Exception 异常
     */
    @Override
    public Object onBytes(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
        String text = new String(bytes, TioConstant.CHARSET);
        log.info("收到byte消息:{},{}", bytes, text);
        ByteBuffer buffer = ByteBuffer.allocate(bytes.length);
        buffer.put(bytes);
        return buffer;
    }

    /**
     * 通道关闭
     *
     * @param wsRequest      请求
     * @param bytes          字节数组
     * @param channelContext 通道
     * @return 空对象
     * @throws Exception 异常
     */
    @Override
    public Object onClose(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
        Tio.remove(channelContext, "close");
        return null;
    }

    /**
     * 收到文本消息
     *
     * @param wsRequest      请求
     * @param text           内容
     * @param channelContext 通道
     * @return 响应内容
     * @throws Exception 异常
     */
    @Override
    public Object onText(WsRequest wsRequest, String text, ChannelContext channelContext) throws Exception {
        WsSessionContext wsSessionContext = (WsSessionContext) channelContext.get();
        //获取websocket握手包
        HttpRequest httpRequest = wsSessionContext.getHandshakeRequest();
        log.debug("握手包:{}", httpRequest);
        log.debug("收到text消息:{}", text);
        // 心跳消息
        if (StrUtil.equalsIgnoreCase(TioConstant.PING_TEXT, text)) {
            return TioConstant.PONG_TEXT;
        } else {
            JSONObject msgJson = JSONUtil.parseObj(text);
            //业务分发
            Integer type = msgJson.getInt("type");
            String toId = msgJson.getStr("toId");
            String msg = msgJson.getStr("msg");
            WsResponse wsResponse = WsResponse.fromText(msg, TioConstant.CHARSET);
            SetWithLock<ChannelContext> channel = Tio.getByUserid(channelContext.tioConfig, toId);
            System.out.println(channel);
            Tio.sendToUser(channelContext.tioConfig, toId, wsResponse);
        }
        return null;
    }
}
